﻿using System;
using System.Linq;
using System.Collections.Generic;
using EPiServer.Shell.Gadgets;
using EPiServer.Shell;
using System.Reflection;
using EPiServer.Research.MobileCenter.JSON;
using EPiServer.Research.MobileCenter.GadgetHelper;
using System.Web.Mvc;

namespace EPiServer.Research.MobileCenter.Core
{

    /// <summary>
    /// MobileCenterFactory is the class that generates the JSON 
    /// needed for the MobileCenter to interpret which gadgets are 
    /// active and if they have any extra information
    /// </summary>
    public class MobileCenterFactory
    {
        static MobileCenterFactory instance = null;
        static readonly object padlock = new object();

        public static MobileCenterFactory Instance
        {
            get
            {
                lock (padlock)
                {
                    if (instance == null)
                    {

                        instance = new MobileCenterFactory();
                    }
                    return instance;
                }
            }
        }

        public MobileCenterFactory()
        {
            GadgetFactory = ShellContext.Instance.Container.GetExportedValue<IGadgetFactory>();
        }
       
        public IGadgetFactory GadgetFactory { get; set; }

        /// <summary>
        /// Gets all json for Mobile.
        /// </summary>
        /// <returns>an JSONGadgetHandler that is later converted to string JSON for the webservice</returns>
        public JSONGadgetHolder GetAllJsonForMobileCenter()
        {
            JSONGadgetHolder gadgetHolder = new JSONGadgetHolder();
            gadgetHolder.gadgets = new List<JSONGadget>();

            var listofgadgets = DDSStorage.Instance.GetAllActivatedGadgets();

            foreach (var gadget in GadgetFactory.GetGadgetTemplates())
            {
                //if a gadget is MobileCenter friendly and is checked to be shown on the MobileCenter
                if (listofgadgets.Select(gad => gad.Name).Contains(gadget.Title))
                {
                    JSONGadget start = new JSONGadget();
                 
                    Type t = gadget.Definition.ControllerType;
                    Object obj = Assembly.GetAssembly(t).CreateInstance(t.FullName);

                    if (obj.GetType().IsSubclassOf(typeof(MobileCenterJsonBase)))
                    {
                        MobileCenterJsonBase controller = (MobileCenterJsonBase)obj;
                        start = GenerateGenericStartInformation(gadget);

                        if (controller.ShouldReturnList)
                        {
                            start.gadgets = GenerateListFromCell(controller.GetListView(), gadget.Title);
                        }
                        else
                        {
                            start.gadgets.Add(GenerateWebCell(controller.GetWebView(), gadget.Title));
                        }
                    }
                    else
                    {

                        start = GenerateGenericGadgetInformation(gadget);  
                    }

                    gadgetHolder.gadgets.Add(start);
                }
            }

            return gadgetHolder;
        }

        /// <summary>
        /// Generates the generic gadget information.
        /// </summary>
        /// <param name="g">The g.</param>
        /// <returns></returns>
        private JSONGadget GenerateGenericGadgetInformation(Gadget g)
        {
            JSONGadget start = GenerateGenericStartInformation(g);

            JSONGadget webcell = new JSONGadget();
            webcell.name = g.Title;
            webcell.type = GadgetUtil.WebView;
            webcell.url = GadgetUtil.GetGadgetUrl(g.Title);
            webcell.gadgets = new List<JSONGadget>();
            start.gadgets.Add(webcell);
            return start;
        }

        /// <summary>
        /// Generates the generic start information.
        /// </summary>
        /// <param name="g">The gadget</param>
        /// <returns></returns>
        private JSONGadget GenerateGenericStartInformation(Gadget g)
        {
            JSONGadget start = new JSONGadget();
            start.name = g.Title;
            start.type = GadgetUtil.StartCell;
            start.url = GadgetUtil.ConstructIconUrl(g.IconUrl);
            start.gadgets = new List<JSONGadget>();
            return start;
        }

        /// <summary>
        /// Generates the list from cell.
        /// </summary>
        /// <param name="cList">The cell list.</param>
        /// <param name="gadgetname">The gadget name.</param>
        /// <returns></returns>
        private List<JSONGadget> GenerateListFromCell(List<CellView> cList, string gadgetname)
        {
            List<JSONGadget> gadgets = new List<JSONGadget>();

            foreach (var cellview in cList)
            {
                JSONGadget g = new JSONGadget();
                g.name = cellview.Name;
                g.type = GadgetUtil.Cell;
                g.url = String.Empty;

                if (cellview.ChildCells != null)
                {
                    g.gadgets = GenerateListFromCell(cellview.ChildCells, gadgetname);
                }
                else
                {
                    g.gadgets.Add(GenerateWebCell(cellview.WebViewToPush, gadgetname));
                }
                gadgets.Add(g);
            }

            return gadgets;
        }

        /// <summary>
        /// Generates the web cell.
        /// </summary>
        /// <param name="c">The ell.</param>
        /// <param name="gadgetname">The gadget name.</param>
        /// <returns></returns>
        private JSONGadget GenerateWebCell(WebView c, string gadgetname)
        {
            JSONGadget webcell = new JSONGadget();
            webcell.name = c.Name;
            webcell.type = GadgetUtil.WebView;

            if (c.UseDefaultUrl)
            {
                webcell.url = GadgetUtil.GetGadgetUrl(gadgetname);
            }
            else
            {
                webcell.url = c.CustomUrl;
            }

            return webcell;
        }
    }
}
